package data.hierarchy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import data.base.Material;
import data.base.Vector3;
import data.base.Vertex;
import data.complex.Triangle;


public class TriangleGroup implements Iterable<Triangle>{
  private List<Triangle> triangles;
  private Set<String> tags;
  private Material material;

  public TriangleGroup(){
    triangles = new ArrayList<Triangle>();
  }

  public void addTriangle(Triangle t, boolean setGroupAtTriangle){
    triangles.add(t);
    if(setGroupAtTriangle)
      t.setGroup(this);
  }

  @Override
  public Iterator<Triangle> iterator() {
    return triangles.iterator();
  }
  
  public int getTriangleCount(){
    return triangles.size();
  }

  public void generateSmoothedVertexNormals(){
    Map<Vertex, Vector3> vxNormals = new HashMap<Vertex, Vector3>();
    for(Triangle t : this){
      if(vxNormals.get(t.getA()) == null){
        vxNormals.put(t.getA(), new Vector3(0, 0, 0));
      }
      if(vxNormals.get(t.getB()) == null){
        vxNormals.put(t.getB(), new Vector3(0, 0, 0));
      }
      if(vxNormals.get(t.getC()) == null){
        vxNormals.put(t.getC(), new Vector3(0, 0, 0));
      }
    }
    for(Triangle t : this){
      vxNormals.get(t.getA()).add(t.getNormal(true));
      vxNormals.get(t.getB()).add(t.getNormal(true));
      vxNormals.get(t.getC()).add(t.getNormal(true));
    }
    for(Vector3 n : vxNormals.values()){
      n.normalize();
    }
    for(Triangle t : this){
      t.getA().setNormal(vxNormals.get(t.getA()));
      t.getB().setNormal(vxNormals.get(t.getB()));
      t.getC().setNormal(vxNormals.get(t.getC()));
    }
  }
  
  public Set<String> getTags(){
    if(tags == null){
      tags = new HashSet<String>();
    }
    return tags;
  }
  
  public Material getMaterial() {
    if(material == null){
      material = Material.DEFAULT;
    }
    return material;
  }

  public void setMaterial(Material material) {
    this.material = material;
  }
}
